% Exemplo de relatório técnico do IC
% Criado por P.J.de Rezende antes do Alvorecer da História.
% Modificado em 97-06-15 e 01-02-26 por J.Stolfi.
% Last edited on 2003-06-07 21:12:18 by stolfi

% modificado em 1o. de outubro de 2008

\documentclass[11pt,twoside]{article}

\usepackage{epsf}
\usepackage{graphicx}
\usepackage{techrep-ic}
\usepackage{makeidx}    % allows for indexgeneration
\usepackage{amsthm}
\usepackage{cite}
\usepackage{rotating}
\usepackage{float}

%%% SE USAR INGLÊS, TROQUE AS ATIVAÇÕES DOS DOIS COMANDOS A SEGUIR:
\usepackage[brazil]{babel}
%% \usepackage[english]{babel}

%%% SE USAR CODIFICAÇÃO LATIN1, TROQUE AS ATIVAÇÕES DOS DOIS COMANDOS A
%%% SEGUIR:
%% \usepackage[latin1]{inputenc}
\usepackage[utf8]{inputenc}

\usepackage{color}
\usepackage{listings}
\lstset{ %
backgroundcolor=\color{white},  % choose the background color. You must add \usepackage{color}
basicstyle=\ttfamily\small,
numberstyle=\small,
keywordstyle=\color{black}\bfseries,
language=Java,                % choose the language of the code
showspaces=false,               % show spaces adding particular underscores
showstringspaces=false,         % underline spaces within strings
showtabs=false,                 % show tabs within strings adding particular underscores
frame=single,                   % adds a frame around the code
tabsize=4,              % sets default tabsize to 2 spaces
captionpos=b,                   % sets the caption-position to bottom
breaklines=true,        % sets automatic line breaking
breakatwhitespace=false,    % sets if automatic breaks should only happen at whitespace
columns=fullflexible,
escapeinside={\%}{)}          % if you want to add a comment within your code
}

\lstnewenvironment{shell}
	{\lstset{language=csh, frame=single}}
	{}

\begin{document}

%%% PÁGINA DE CAPA %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% Número do relatório

\TRNumber{02}

% DATA DE PUBLICAÇÃO (PARA A CAPA)
%
\TRYear{10}  % Dois dígitos apenas
\TRMonth{04} % Numérico, 01-12

% LISTA DE AUTORES PARA CAPA (sem afiliações).
\TRAuthor{E. B. Prata \and G. S. de Paula \and P. R. Costa \and R. Dominiquini}

% TÍTULO PARA A CAPA (use \\ para forçar quebras de linha).
\TRTitle{Sub-Projeto 2:\\Transporte UDP}

\TRMakeCover

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% O que segue é apenas uma sugestão - sinta-se à vontade para
% usar seu formato predileto, desde que as margens tenham pelo
% menos 25mm nos quatro lados, e o tamanho do fonte seja pelo menos
% 11pt. Certifique-se também de que o título e lista de autores
% estão reproduzidos na íntegra na página 1, a primeira depois da
% página de capa.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Nomes de autores ABREVIADOS e titulo ABREVIADO,
% para cabeçalhos em cada página.
%
\markboth{Prata, De Paula, Costa e Dominiquini}{Multicast}
\pagestyle{myheadings}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% TÍTULO e NOMES DOS AUTORES, completos, para a página 1.
% Use "\\" para quebrar linhas, "\and" para separar autores.
%
\title{Sub-Projeto 2: Transporte UDP}

\author{
Eduardo Jacob Prata\thanks{Instituto  de Computação, Universidade
Estadual  de Campinas, 13081-970  Campinas,  SP.}  \and
Gustavo de Paula\footnotemark[1] \and
Paulo de Almeida Costa\footnotemark[1] \and
Rafael Baboni Dominiquini\footnotemark[1]}

\date{}

\maketitle

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{abstract} 

Neste relatório descrevemos o subprojeto 2, que trata da criação do componente de transporte UDP para o projeto e da realização de um série de testes para Ethernet utilizando este componente. Também foram criados testes unitários para verificação do funcionamento do componente. Com relação aos testes com Ethernet conseguimos verificar que a latência é em geral baixa para distâncias pequenas mesmo com sobrecarga na troca de mensagens. Obtivemos média de 6.5 ms e desvio padrão de 11 ms para a latência, notando que a mediana é de 2.26 ms, representando melhor o conjunto de dados. O jitter também é baixo, com média de 0.37 ns, mediana de 0.28 ms e desvio padrão de 1.41 ms, mostrando que a latência de modo geral não sofre grandes variações. Verificamos também que não há troca na ordem de recbimento das mensagens enviadas por um mesmo processo, o que costuma ocorrer é a perda de mensagens pela falta de confiabilidade do UDP.

\end{abstract}

\section{Introdução}

O UDP (User Datagram Protocol) é um dos principais protocolos utilizados na Internet e em redes Ethernet de modo geral. Com o UDP, aplicações podem enviar mensagens, chamadas  de datagramas, para outros hosts em uma rede IP. O protocolo foi criado por David P. Reed em 1980 e formalmente definido no RFC 768~\cite{rfc768}. Ele utiliza um sistema simples de transmissão sem hand-shaking inicial, não garantindo confiabilidade, ordenação ou integridade dos dados.

Por seu caráter stateless o UDP é utilizado em aplicações distribuídas do tipo em que poucos servidores respondem a um número imenso de clientes, aumentando o desempenho pelo fato de não haver estabelecimento de conexão. No caso de aplicações distribuídas como a de nosso projeto, com foco em operação assíncrona e uso de multicast, o UDP se mostra fundamental.

O subprojeto 2 se divide em três etapas distintas, o desenvolvimento de classes para implementar o transporte UDP multicast e unicast, o desenvolvimento de Unit Tests com o uso de JUnit e a execução de testes para medir a latência, jitter e ordenação das mensagens UDP trocadas pelo componente de transporte. As próximas seções explicam estas etapas.

\section{Implementação da camada de transporte}

O componente de transporte segue interfaces bem definidas fornecidas como requisitos do projeto. As classes que desenvolvemos implementam estas interfaces utilizando métodos do pacote java.net contendo a implementação UDP da Java Library. Além destas classes utilizamos também uma classe já fornecida no início do projeto chamada Marshall. Ressaltamos que decidimos implementar as classes de maneira independente mesmo tendo acesso à implementação padrão das mesmas.

\subsection{Classe Marshall}

Esta classe implementa dois métodos estáticos, marshall e unmarshall. Estes métodos fazem a serialização e desserialização de objetos. Basicamente, o método marshall transforma o objeto em um vetor de bytes para envio pela rede e o método unmarshall recebe um vetor de bytes e reconstrói de volta o objeto. Ambos utilizam streams de objeto do pacote java.io para escrita e leitura dos objetos.

\subsection{Classe UDPTransportId}

Esta classe representa a identificação única de cada processo dentro do grupo de processos. No nosso caso a identificação única é o IP concatenado à porta no qual o processo recebe mensagens de unicast. Ela é única porque dentro da mesma rede o endereço IP de diferentes hosts é diferente, e dentro de um mesmo host a porta é diferente para cada socket UDP. A concatenação torna a identificação única seja para processos em máquinas diferentes ou na mesma máquina.

O \emph{UDPTransportId} também implementa a interface \emph{Comparable}, para isso definimos os métodos \emph{equals} e \emph{compareTo}. O método equals verifica se duas identificações são iguais, comparando o IP e a porta, e o método \emph{compareTo} retorna o resultado de comparação de duas identificações, dizendo se a primeira é maior, menor ou igual à segunda. 

\subsection{Classe UDPMessage}

A classe \emph{UDPMessage} é mais simples, ela possui apenas 4 métodos públicos. O construtor instancia uma nova mensagem com o payload (carga) da mensagem, a identificação do remetente e a do destinatário. Os outros métodos públicos são para obtenção do payload, da identificação do remetente e do destinatário.

\subsection{Classe UDPTransport}

Esta classe implementa de fato a comunicação UDP. No método construtor da classe são instanciados dois sockets, um para comunicação unicast e outro para broadcast. Para possibilitar a comunicação em multicast, é feita a inscrição em um grupo de multicast no endereço 225.0.0.0 com a porta 5679. Ainda no construtor são iniciadas duas novas threads que ficam ouvindo nestas portas dentro de um laço infinito. Quando alguma mensagem chega por alguma porta através destas threads, ela é enfileirada.

Para se encontrar o endereço que deve ser usado no bind, uma mensagem é enviada repetidamente no endereço multicast. Este envio é feito em uma outra porta para não interferir com as trocas normais de mensagens. Ao mesmo tempo, fica-se ouvindo todas as mensagens que chegam, até receber um eco da mensagem enviada. Quando o eco é recebido, o IP do remetente é usado como endereço do processo. Este procedimento está implementado no método \emph{allocAddress()}.

Quando o método \emph{receiveMessage()} é invocado, ele retorna a mensagem do início da fila, ou bloqueia até a recepção de alguma mensagem. O método \emph{receiveMessage(int timeout)} funciona de forma análoga, mas o bloqueio não poderá demorar mais de timeout milisegundos. O sistema de bloqueio foi implementado com o uso de um semáforo, ele é inicializado com valor zero e a cada mensagem recebida é incrementado e é decrementado a cada retirada de mensagem da pilha. Quando um processo tenta obter uma mensagem da fila vazia o semáforo tem valor zero e, portanto, ele bloqueia.

Outro método da classe é o \emph{sendMessage()}, que envia a mensagem para o processo destinário, ou em multicast, para todos os processos. No caso de mensagens de Ping, utilizadas para a medição de Latência e de Jitter, um novo timestamp é adicionado antes do envio.

Caso outros grupos de multicast estejam presentes na rede não há problemas desde que a porta utilizada para o grupo seja diferente. Se a porta for a mesma ambos os sistemas receberão mensagens indevidas do outro grupo podendo corromper a funcionalidade desejada do sistema. O uso do grupo de multicast em conjunto com a identificação de processos permite que os processos se comuniquem sem saber de maneira explícita a existência uns dos outros. Ao receber uma mensagem multicast o processo descobre quem a enviou e pode conversar diretamente com o processo remetente, com unicast o funcionamento é análogo.

\section{Testes Unitários}

Para testar a classe UDPTransport criamos uma série de testes unitários (unit tests) utilizando o framework JUnit. Testes unitários consistem em validar o funcionamento de funções através da entrada de parâmetros válidos e inválidos nas funções e a verificação dos resultados das mesmas. O JUnit facilita esta tarefa ao prover um mecanismo simples para criação e execução de testes. Ao extender a classe TestCase cada método com nome iniciado por \emph{test} é um teste e será executado. O método \emph{setUp} permite a definição de parâmetros iniciais para os testes.

O JUnit fornece métodos de verificação do tipo assert, similares ao que existe na libc. É possível utilizar asserts para verificar que um valor é nulo ou falso, ou que dois valores são iguais, apenas citando alguns casos. Para testar o \emph{UDPTransport} foram criados 7 testes na classe \emph{UDPTransportTest}. Todos os testes foram feitos em máquina local porque o JUnit não fornece um bom suporte para testes distribuídos. Os testes foram os seguintes:

\begin{itemize}

	\item \textbf{testMyID:} Este teste verifica a unicidade dos identificadores gerados na classe \emph{UDPTransportId} e \emph{UDPTransport}. São criados 100 sockets e um laço verifica se há algum identificador repetido.

	\item \textbf{testEcho:} Testa o envio de uma mensagem na qual o destinatário e o remetente são o mesmo processo. Apenas um socket é instanciado e verifica-se se o dado é recebido e é igual ao que foi enviado.

	\item \textbf{testSend:} Teste do envio em unicast de uma mensagem de um socket para outro na mesma máquina e verifica a integridade da mensagem.
\begin{sloppypar}
	\item \textbf{testMultPayloads:} Testa o envio de múltiplas mensagens relativamente grandes (múltiplos de 1 MTU) em unicast entre dois sockets na mesma máquina, verifica como ocorre a fragmentação e desfragmentação da mensagem.
\end{sloppypar}
	\item \textbf{testQueue:} Testa a fila de mensagens no receptor, a ordem das mensagens recebidas deve ser a mesma do envio. As mensagens são enviadas e recebidas pelo mesmo socket.

	\item \textbf{testMulticast:} Testa o envio de uma mensagem em multicast de um mesmo socket. Além do socket remetente, outro socket instanciado deve receber a mensagem.

	\item \textbf{testMulticastBigPayloads:} Testa o envio de múltiplas mensagens em multicast e unicast. Este primeiro socket deve receber apenas as mensagens unicast vindas dele mesmo. Outro socket instanciado deve receber ambas as mensagens.

\end{itemize}

Em todos os testes é verificado se houve perda de mensagens, se houve troca de ordem entre elas ou até mesmo se alguma foi corrompida durante o transporte. Em caso de algum comportamento inesperado, um aviso é emitido. A implementação final passou em todos os testes. Vale ressaltar que os testes assumem que apenas serão recebidas as mensagens que fazem parte de do caso de teste, isto é, o envio de mensagens em paralelo, especialmente envios em multicast, poderá afetar o resultado do teste.

\section{Medição de Latência e Jitter na Ethernet}

\subsection{Experimento}

Para obter medidas de latência e jitter na Ethernet criamos um pacote que utiliza o componente de transporte que desenvolvemos para o envio e recebimento de mensagens multicast e unicast. Criamos três classes: \emph{Communicator}, \emph{PingMessage} e \emph{Log}. As classes \emph{PingMessage} e \emph{Log} são auxiliares e a classe \emph{Communicator} contém o código para execução do teste.

A classe \emph{PingMessage} faz a vez de payload das mensagens trocadas. Nela armazenamos os timestamps gerados nos envios e recebimentos da mensagem, o número da mensagem e o identificador do remetente da mensagem, além de uma \emph{String} que simula uma mensagem que seria trocada em um caso real. Para o teste a \emph{String} é um texto aleatório com tamanho parametrizado. A classe possui quatro métodos públicos, o método \emph{toString} retorna todos os timestamps da mensagem concatenados, o método \emph{append} adiciona um novo timestamp à mensagem, o método \emph{getLatency} aplica a fórmula de cálculo de latência aos timestamps e retorna este valor e, finalmente, o método \emph{getFirstTimestamp} retorna o primeiro timestamp da mensagem, que é o tempo em que a mensagem foi enviada pelo remetente. A classe \emph{Log} é um utilitário que utiliza o pacote \emph{log4j} para controlar a emissão de mensagens de logs. Na classe \emph{Communicator} utilizamos métodos estáticos da classe \emph{Log} para gerar mensagens de debug.

A parte principal do código está nas classes \emph{Communicator} e \emph{UDPTransport}. Os principais métodos da classe \emph{Communicator} são \emph{sendPing} e \emph{receivePing}. Os processos do sistema são de dois tipos, o sender é o que envia as mensagens e ao receber uma resposta grava a latência da mensagem, o receiver retira mensagens da fila e as envia de volta para o remetente.

A gravação dos timestamps é feita na classe UDPTransport, o método de envio de mensagem grava o timestamp de envio e o de receber grava o timestamp na mensagem no momento em que ela é recebida, antes de colocá-la na fila de mensagens. Para gravar os timestamps utilizamos os métodos do próprio objeto PingMessage contido no payload, com isso concentramos toda a funcionalidade de medição de tempo na classe PingMessage. Os timestamp são obtidos em nanosegundos com o método \emph{System.nanoTime()}. Mesmo não tendo relação direta com tempo real, podemos utilizar este método com segurança porque para calcular a latência utilizamos apenas a duração de intervalos. Um dos intervalos é tirado no sender, tempo do envio inicial e recebimento final, e o outro no receiver, tempo de recebimento e reenvio para o sender. Utilizamos uma viagem de ida-e-volta para aumentar a precisão do teste, com isso geramos um RTT (round-trip time) e a latência é $RTT/2$. Não necessitamos de sincronização de relógios neste teste por conta da fórmula que utilizamos para cálculo da latência, que leva em conta apenas intervalos e não o tempo real.

Na classe \emph{Communicator} o método \emph{sendPing} simplesmente envia uma mensagem em multicast. O método \emph{receivePing}, ao receber uma mensagem nova de outro remetente, grava em um arquivo o número da mensagem e a reenvia ao remetente, os timestamps são adicionados pelo transporte. O processo sender, ao receber a resposta de uma mensagem originada por ele, calcula e grava em um arquivo a latência utilizando a fórmula: $[(t3-t0)-(t2-t1)]/2$. Sendo t0 o tempo no envio inicial da mensagem, t1 o tempo no recebimento da mensagem pelo receiver, t2 o tempo no reenvio da mensagem do receiver para o sender e t3 o tempo no recebimento da mensagem pelo sender. Utilizamos esta fórmula mesmo sabendo que os tempos do destinatário, t1 e t2, são praticamente idênticos.

Criamos uma thread para recebimento e outra para o envio de mensagens para aumentar o paralelismo. Um processo do tipo sender executa as duas threads porque o experimento utliza envio de ping e recebimento de pong (round-trip). Já o processo do tipo receiver executa apenas a thread de recebimento.

\subsection{Análise dos Dados}

Utilizamos uma sequência de scripts para tratar os dados do teste, gerando resultados como média e desvio padrão, além de uma série de gráficos. O primeiro script é um script python que faz um parsing dos resultados, elimina os valores do primeiro e último minuto, calcula todos os valores de jitter e grava os resultados em novos arquivos de log. Para obter medidas de média, erro e gerar histogramas utilizamos o software R, um ambiente livre para computação estatística. Criamos um script apenas para produzir estes dados e gráficos utilizando os logs gerados na etapa anterior. Geramos também outros gráficos utilizando o programa gnuplot, geramos gráficos para a latência em função do tempo, jitter em função do tempo, e fittings com acsplines para o jitter com o objetivo de facilitar a visualização dos resultados.

O experimento é executado durante 10 minutos. O primeiro e último minuto são eliminados porque eles contém pontos com erro muito elevado já que a rede ainda não está em um estado estável, consideramos que entre o segundo e penúltimo minuto o sistema entra no chamado \emph{steady-state}, em que os atrasos se tornam mais uniformes. O resultado final do teste é a um arquivo em que cada linha contém o tempo transcorrido seguido da latência de cada mensagem trocada. Para nossos experimentos executamos um processo como sender e três outros como receivers, todos localizados em máquinas diferentes. Com o uso do script para parsing produzimos um novo log com os dados de latência do minuto 1 a 9 e dados de jitter do mesmo intervalo. Os resultados obtidos, incluindo os gráficos, são descritos na seção a seguir.

\subsection{Resultados}

\begin{figure}[ht!]
    \centering    
    \includegraphics[scale=0.5]{plot_latency.jpg}
    \caption{Gráfico de latência versus tempo.}
    \label{fig:plot_latency}
\end{figure}

\begin{figure}[ht!]
  \centering
    \includegraphics[scale=0.5]{hist_latency.jpg}
    \caption{Histograma de latências.}
    \label{fig:hist_latency}
\end{figure}

Após a análise dos dados chegamos em alguns valores para a latência e o jitter. Para a latência temos os seguintes dados: média de 6.55 ms, mediana de 2.26 ms e desvio padrão de 11.09 ms. Para o jitter obtivemos os seguintes valores: média de 0.36 ns, mediana de 0.28 ms e desvio padrão de 1.42 ms. Podemos explicar o alto desvio padrão da latência por conta da série de picos de latência obtidos em alguns períodos, estes picos podem ser vistos na Figura~\ref{fig:plot_latency}. O baixo valor para a mediana e média do jitter ocorre por que os valores, como vistos na Figura~\ref{fig:plot_jitter}, se encontram entre a faixa de -2 a +2 ms, com a média bem próxima de zero.

\begin{figure}[ht!]
    \centering
    \includegraphics[scale=0.5]{plot_jitter.jpg}
    \caption{Gráfico de jitter versus tempo.}
    \label{fig:plot_jitter}
\end{figure}

O gráfico da Figura~\ref{fig:plot_latency} mostra que em geral as latências são baixas, entre 1 e 4 ms. Os picos de latência vistos podem ter sido causados por períodos em que muitas mensagens trafegavam pela rede e o buffer dos roteadores estavam muito cheios. Já quanto ao jitter, os valores são mais uniformes. Há uma faixa bem uniforme entre -0.5 e +0.5 ms, com poucos valores extrapolando esta faixa. Esta pequena variabilidade mostra não há saltos grandes nas latências, mesmo quando a latência atinge valores altos, o faz de modo gradual. Os gráficos nas Figuras \ref{fig:plot_jitter}, \ref{fig:hist_jitter} e \ref{fig:fit_jitter} complementam estas informações.

\begin{figure}[ht!]
    \centering
    \includegraphics[scale=0.5]{hist_jitter.jpg}
    \caption{Histograma de jitters.}
    \label{fig:hist_jitter}
\end{figure}

\begin{figure}[ht!]
    \centering    
    \includegraphics[scale=0.5]{fit_jitter.jpg}
    \caption{Fit de jitters com acsplines.}
    \label{fig:fit_jitter}
\end{figure}

\section{Verificação da Ordenação de Mensagens na Ethernet}

\subsection{Experimento}

O mesmo pacote usado para se calcular a latência e o jitter das mensagens trocadas produz um log que pode ser usado na verificação de perdas e trocas de ordem nas mensagens. Como feito para o teste anterior, uma máquina fazendo o papel de sender envia repetidamente inúmeras mensagens por um tempo pré-estabelecido gravando em cada mensagem o timestamp local.

Cada um dos destinatários, ao receber uma mensagem da máquina remetente, grava em um arquivo o timestamp registrado junto com o número da mensagem. O número de cada mensagem é único e crescente, contanto que haja apenas um sender em funcionamento.

Analisando o arquivo de log gerado é fácil constatar se houve ou não troca de mensagens. Se uma mensagem de número menor estiver depois na fila do que uma mensagem de número maior significa que houve troca de ordem. É fácil também verificar se houve alguma mensagem perdida no processo, já que o as mensagens recebidas no destinatário devem ser sempre crescentes com incremento 1. Um script em python automatiza esta verificação.

Nenhum teste com mais de um remetente foi possível, pois a única forma dos destinatários compararem a ordem de envio é comparando o timestamp das mensagens recebidas, os timestamps não são estritamente crescentes para diversos processos já que não conseguimos obter a sincronização dos relógios no laboratório de testes. Caso tivéssemos um sistema sincronizado com NTP seria possível criar N processos iguais, que enviam e recebem mensagens e testar se as mensagens recebidas pelos processos possuem uma ordem natural e a ordem do recebimento é idêntica em todos eles. Caso este fato se mostrasse verdadeiro para redes Ethernet de pequeno tamanho e de apenas 1 hop seria trivial implementar algoritmos distribuídos dependentes de sincronização, já que a mesma seria provida pela camada de rede, sem a necessidade do uso de complicados algoritmos de sincronização na camada de aplicação.

\subsection{Resultados}

Em um teste são trocadas cerca de 160000 mensagens, das quais cerca de 125000 foram analisadas, eliminando-se o primeiro e último minuto. Decidimos instanciar um remetente e três destinatários para a análise. Em todos os testes que fizemos, não constatamos nenhuma troca de mensagens. Em testes com envio de grandes mensagens de forma rápida, houve um número não desprezível de mensagens perdidas. A ausência de troca de mensagens demonstra que, pelo menos, os segmentos de rede entre os processos funcionam aproximadamente como uma fila FIFO, removendo a necessidade de simular esta característica na camada de transporte.

Nos teste finais, percebemos que um dos destinatários deixou de receber 31 mensagens, o que é um valor bem baixo, dado o total de mensagens. Esta perda pode ser ocasionada por algum evento na máquina em que o teste estava rodando.

\section{Conclusão}

Neste subprojeto completamos o desenvolvimento do componente de transporte de nossa aplicação. Este componente será primordial no decorrer do projeto porque é ele que se encarregará da troca de mensagens entre todos os processos distribuídos e, portanto, sua eficiência é refletida diretamente na eficiência da aplicação.

Através dos diversos testes e experimentos que realizamos conseguimos demonstrar o bom funcionamento do componente e também algumas características da Ethernet com múltiplos segmentos, como a baixa troca de ordem entre as mensagens em redes de apenas um hop e também baixa variabilidade entre a latência de diferentes mensagens para segmentos de mesmo tamanho aproximado.

\begin{thebibliography}{1}

\bibitem{rfc768}
J.~Postel.
\newblock {RFC 768}: User datagram protocol, August 1980.

\end{thebibliography}

\end{document}
